<?php
class Workflow_Engine
{
	/**
     * Zend_Db_Adapter_Abstract instance to be used.
     *
     * @var Zend_Db_Adapter_Abstract
     */
    protected $db;    

    /**
     * Construct a new database definition handler.
     *
     * This constructor is a tie-in.
     *
     * @param Zend_Db_Adapter_Abstract $db
     */
    public function __construct( Zend_Db_Adapter_Abstract $db )
    {
        $this->db = $db;        
    }
        
    public function deployWorkflowDefinition($xmlDirectory, $workflowName, $workflowVersion = 0)
    {
    	$svc = new Workflow_DefinitionStorage_Xml($xmlDirectory);
    	$workflow = $svc->loadByName($workflowName, $workflowVersion);
    	
    	$dbsvc = new Workflow_DefinitionStorage_Database($this->db);
    	$dbsvc->save($workflow);
    }
    
    public function writeWorkflowDefinitionToXml($xmlDirectory, $workflowName, $workflowVersion = 0)
    {
    	$dbsvc = new Workflow_DefinitionStorage_Database($this->db);
    	$workflow = $dbsvc->loadByName($workflowName, $workflowVersion);
    	
    	$xml = new Workflow_DefinitionStorage_Xml($xmlDirectory);
    	$xml->save($workflow);
    }
    
    public function startWorkflow($workflowName, $workflowVersion = 0)
    {
    	$db = new Workflow_DefinitionStorage_Database($this->db);
    	$workflow = $db->loadByName($workflowName, $workflowVersion);
    	
    	$execution = new Workflow_Execution_Database($this->db);
    	$execution->workflow = $workflow;
    	return $execution->start();
    }
    
    public function getUserStartableWorkflow($userId)
    {
    	$result = $this->db->fetchAll("SELECT w.workflow_id, w.workflow_name, max(w.workflow_version) as workflow_version,
    									 w.workflow_created, w.workflow_alias, w.workflow_description, w.workflow_category_id
										from workflow_start_candidates uw, workflow w
										WHERE uw.workflow_id = w.workflow_id										
										and uw.user_id = ?
										group by w.workflow_name", $userId);
    	return $result;
    }
    
    public function startManualWorkflow($workflowId)
    {
    	$db = new Workflow_DefinitionStorage_Database($this->db);
    	$workflow = $db->loadById($workflowId);
    	
    	$execution = new Workflow_Execution_Database($this->db);
    	$execution->workflow = $workflow;
    	
    	$execution->start();
    	    	
    	if ($workflow->isManualStart()) 
    	{
    		$firstManualNode = $workflow->startNode->getFirstOutNode()->getId();
    		
    		return $this->renderUserTask($firstManualNode, $execution);    		
    	}
    	
    	return "";
    }
    
    public function completeUserTask($executionId, $taskNodeId, array $inputData = array())
    {
    	$execution = new Workflow_Execution_Database($this->db, $executionId);
    	
    	$svc = new Workflow_Service_UserTask($execution->getDb());
    	$svc->setTaskCompleted($execution->workflow->id, $execution->getId(), $taskNodeId);
    	
    	$execution->resume($inputData);
    }
    
    public function getUserToDoWorkItem($userId)
    {
    	$svc = new Workflow_Service_UserTask($this->db);
    	return $svc->getUserWorkItem($userId);    	
    }
    
    public function renderUserTask($nodeid, Workflow_Execution $execution)
    {
    	$node = $execution->workflow->getNode($nodeid);
    	if ($node)
    	{
    		$nodeConfig = $node->getConfiguration();
    		$renderclass = $nodeConfig['Render'];
    		$rendercontent = $nodeConfig['RenderContent'];
    		$render = new $renderclass($rendercontent, array(
    			'executionId' => $execution->getId(),
    			'taskNodeId' => $nodeid,
    		));
    		return $render->render($execution);    		
    	}
    	    	
    	return "";
    }
    
    public function renderUserWorkItem($executionId, $taskNodeId)
    {
    	$execution = new Workflow_Execution_Database($this->db, (int)$executionId);
    	$node = $execution->workflow->getNode($taskNodeId);
    	if ($node)
    	{
    		$nodeConfig = $node->getConfiguration();
    		$renderclass = $nodeConfig['Render'];
    		$rendercontent = $nodeConfig['RenderContent'];
    		$render = new $renderclass($rendercontent, array(
    			'executionId' => $execution->getId(),
    			'taskNodeId' => $taskNodeId,
    		));
    		return $render->render($execution);    		
    	}   	
    	
    	return "";
    }  

    
    /**
     * Enter description here ...
     * @param array $fields
     * @param integer $state : 0 流转中, 1, 已完成，-1，已取消
     */
    public function getProcessInstance(array $fields, $state = 0)
    {
    	$result = array();
    	
    	if ($state == 0)
    	{
    		$result = $this->db->fetchAll("select * from execution_histroy where isCompleted is null and isCanceled is null");
    	}
    	else if ($state == 1)
    	{
    		$result = $this->db->fetchAll("select * from execution_histroy where isCompleted = 1");
    	}
    	elseif ($state == -1)
    	{
    		$result = $this->db->fetchAll("select * from execution_histroy where isCanceled = 1");
    	}
    	
    	if (! empty($result))
    	{
    		foreach ($result as $row)
    		{
    			$vars = Workflow_DatabaseUtil::unserialize( $row['execution_variables'] );
    			foreach ($fields as $k)
    			{
    				$row[$k] = $vars[$k];
    			}
    		}
    	}
    	
    	return $result;
    }
}
?>